package elastic

import (
	"context"
	"encoding/json"
	"fmt"
	"net/url"
	"strings"
	"time"

	"go-toolkit/library/ecode"

	"github.com/pkg/errors"
)

// KV .
type KV struct {
	*Elastic
	business string
	keys     map[string][]string
}

// NewKV new a request
func (e *Elastic) NewKV(business string) *KV {
	return &KV{
		Elastic:  e,
		business: business,
		keys:     make(map[string][]string),
	}
}

// IndexByMod index by mod
func (kv *KV) IndexByMod(prefix string, val, mod int64) string {
	tmp := mod - 1
	var digit int
	for tmp > 0 {
		tmp /= 10
		digit++
	}
	format := fmt.Sprintf("%s_%%0%dd", prefix, digit)
	return fmt.Sprintf(format, val%mod)
}

// IndexByTime index by time
func (kv *KV) IndexByTime(prefix string, typ indexType, t time.Time) (index string) {
	year := t.Format("2006")
	month := t.Format("01")
	switch typ {
	case IndexTypeYear:
		index = strings.Join([]string{prefix, year}, "_")
	case IndexTypeMonth:
		index = strings.Join([]string{prefix, year, month}, "_")
	case IndexTypeDay:
		day := t.Format("02")
		index = strings.Join([]string{prefix, year, month, day}, "_")
	case IndexTypeWeek:
		index = strings.Join([]string{prefix, year, month, weeks[t.Day()/8]}, "_")
	}
	return
}

// AddKV add kv items
func (kv *KV) AddKV(index string, data ...string) *KV {
	if len(data) == 0 {
		return kv
	}
	kv.keys[index] = append(kv.keys[index], data...)
	return kv
}

// Do post a request
func (kv *KV) Scan(ctx context.Context, result interface{}) (err error) {
	var keys []byte
	keys, err = json.Marshal(kv.keys)
	if err != nil {
		return
	}
	params := url.Values{}
	params.Add("business", kv.business)
	params.Add("keys", string(keys))
	response := new(response)
	if err = kv.client.Post(ctx, kv.c.Host+_pathKV, "", params, &response); err != nil {
		return
	}
	if ecode.Int(response.Code) != ecode.OK {
		err = ecode.Int(response.Code)
	}
	err = errors.Wrapf(json.Unmarshal(response.Data, &result), "scan(%s)", response.Data)
	return
}

// Params get query parameters
func (kv *KV) Params() string {
	keys, _ := json.Marshal(kv.keys)
	return fmt.Sprintf("business=%s&keys=%s", kv.business, keys)
}
